home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / scroll.c < prev    next >
C/C++ Source or Header  |  2008-11-07  |  9KB  |  378 lines

  1. /*
  2.  * Copyright 1994, 1995, 1999 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  *    scroll.c
  12.  *        Scrollbar support
  13.  */
  14.  
  15. #include "globals.h"
  16. #include "appres.h"
  17. #include "ctlr.h"
  18.  
  19. #include "ctlrc.h"
  20. #include "kybdc.h"
  21. #include "screenc.h"
  22. #include "scrollc.h"
  23. #include "selectc.h"
  24. #include "statusc.h"
  25.  
  26. /* Globals */
  27. Boolean    scroll_initted = False;
  28.  
  29. /* Statics */
  30. static unsigned char **buf_save = (unsigned char **) NULL;
  31. static struct ea **ea_save = (struct ea **) NULL;
  32. static int      n_saved = 0;
  33. static int      scroll_next = 0;
  34. static float    thumb_top = 0.0;
  35. static float    thumb_top_base = 0.0;
  36. static float    thumb_shown = 1.0;
  37. static int      scrolled_back = 0;
  38. static Boolean  need_saving = True;
  39. static Boolean  vscreen_swapped = False;
  40. static char    *sbuf = CN;
  41. static int      sa_bufsize;
  42. static char    *zbuf = CN;
  43. static void sync_scroll(int sb);
  44. static void save_image(void);
  45. static void scroll_reset(void);
  46.  
  47. /*
  48.  * Initialize (or re-initialize) the scrolling parameters and save area.
  49.  */
  50. void
  51. scroll_init(void)
  52. {
  53.     register int i;
  54.     int sa_size;
  55.     unsigned char *s;
  56.  
  57.     if (appres.save_lines % maxROWS)
  58.         appres.save_lines =
  59.             ((appres.save_lines+maxROWS-1)/maxROWS) * maxROWS;
  60.     if (!appres.save_lines)
  61.         appres.save_lines = maxROWS;
  62.     if (sbuf != CN) {
  63.         XtFree(sbuf);
  64.         XtFree(zbuf);
  65.         XtFree((char *)buf_save);
  66.         XtFree((char *)ea_save);
  67.     }
  68.     sa_size = appres.save_lines + maxROWS;
  69.     buf_save = (unsigned char **)XtCalloc(sizeof(unsigned char *), sa_size);
  70.     ea_save = (struct ea **)XtCalloc(sizeof(struct ea *), sa_size);
  71.     sa_bufsize = (sa_size * (sizeof(unsigned char) + sizeof(struct ea))) * maxCOLS;
  72.     sbuf = XtMalloc(sa_bufsize);
  73.     zbuf = XtMalloc(maxCOLS);
  74.     (void) memset(zbuf, '\0', maxCOLS);
  75.     s = (unsigned char *)sbuf;
  76.     for (i = 0; i < sa_size; s += maxCOLS, i++)
  77.         buf_save[i] = s;
  78.     for (i = 0; i < sa_size; s += (maxCOLS * sizeof(struct ea)), i++)
  79.         ea_save[i] = (struct ea *)s;
  80.     scroll_reset();
  81.     scroll_initted = True;
  82. }
  83.  
  84. /*
  85.  * Reset the scrolling parameters and erase the save area.
  86.  */
  87. static void
  88. scroll_reset(void)
  89. {
  90.     (void) memset(sbuf, 0, sa_bufsize);
  91.     scroll_next = 0;
  92.     n_saved = 0;
  93.     scrolled_back = 0;
  94.     thumb_top_base = thumb_top = 0.0;
  95.     thumb_shown = 1.0;
  96.     need_saving = True;
  97.     screen_set_thumb(thumb_top, thumb_shown);
  98.     enable_cursor(True);
  99. }
  100.  
  101. /*
  102.  * Save <n> lines of data from the top of the screen.
  103.  */
  104. void
  105. scroll_save(int n, Boolean trim_blanks)
  106. {
  107.     int i;
  108.  
  109.     /* Trim trailing blank lines from 'n', if requested */
  110.     if (trim_blanks) {
  111.         while (n) {
  112.             if (memcmp((char *)(screen_buf+((n-1)*COLS)),
  113.                    zbuf, COLS))
  114.                 break;
  115.             else
  116.                 n--;
  117.         }
  118.         if (!n)
  119.             return;
  120.     }
  121.  
  122.     /* Scroll to bottom on "output". */
  123.     if (scrolled_back)
  124.         sync_scroll(0);
  125.  
  126.     /* Save the screen contents. */
  127.     for (i = 0; i < n; i++) {
  128.         if (i < COLS) {
  129.             (void) memmove(buf_save[scroll_next],
  130.                 screen_buf+(i*COLS),
  131.                 COLS);
  132.             (void) memmove(ea_save[scroll_next],
  133.                 (ea_buf+(i*COLS)),
  134.                 COLS*sizeof(struct ea));
  135.             if (COLS < maxCOLS) {
  136.                 (void) memset((char *)(buf_save[scroll_next] + COLS), '\0',
  137.                     maxCOLS - COLS);
  138.                 (void) memset((char *)(ea_save[scroll_next] + COLS), '\0',
  139.                     (maxCOLS - COLS)*sizeof(struct ea));
  140.             }
  141.         } else {
  142.             (void) memset((char *)buf_save[scroll_next], '\0',
  143.                 maxCOLS);
  144.             (void) memset((char *)ea_save[scroll_next], '\0',
  145.                 maxCOLS*sizeof(struct ea));
  146.         }
  147.         scroll_next = (scroll_next + 1) % appres.save_lines;
  148.         if (n_saved < appres.save_lines)
  149.             n_saved++;
  150.     }
  151.  
  152.     /* Reset the thumb. */
  153.     thumb_top_base =
  154.         thumb_top =
  155.         ((float)n_saved / (float)(appres.save_lines + maxROWS));
  156.     thumb_shown = 1.0 - thumb_top;
  157.     screen_set_thumb(thumb_top, thumb_shown);
  158. }
  159.  
  160. /*
  161.  * Add blank lines to the scroll buffer to make it a multiple of the
  162.  * screen size.
  163.  */
  164. void
  165. scroll_round(void)
  166. {
  167.     int n;
  168.  
  169.     if (!(n_saved % maxROWS))
  170.         return;
  171.  
  172.     /* Zero the scroll buffer. */
  173.     for (n = maxROWS - (n_saved % maxROWS); n; n--) {
  174.         (void) memset((char *)buf_save[scroll_next], '\0', maxCOLS);
  175.         (void) memset((char *)ea_save[scroll_next], '\0',
  176.                 maxCOLS*sizeof(struct ea));
  177.         scroll_next = (scroll_next + 1) % appres.save_lines;
  178.         if (n_saved < appres.save_lines)
  179.             n_saved++;
  180.     }
  181.  
  182.     /* Reset the thumb. */
  183.     thumb_top_base =
  184.         thumb_top =
  185.         ((float)n_saved / (float)(appres.save_lines + maxROWS));
  186.     thumb_shown = 1.0 - thumb_top;
  187.     screen_set_thumb(thumb_top, thumb_shown);
  188. }
  189.  
  190. /*
  191.  * Jump to the bottom of the scroll buffer.
  192.  */
  193. void
  194. scroll_to_bottom(void)
  195. {
  196.     if (scrolled_back) {
  197.         sync_scroll(0);
  198.         /* screen_set_thumb(thumb_top, thumb_shown); */
  199.     }
  200.     need_saving = True;
  201. }
  202.  
  203. /*
  204.  * Save the current screen image, if it hasn't been saved since last updated.
  205.  */
  206. static void
  207. save_image(void)
  208. {
  209.     int i;
  210.  
  211.     if (!need_saving)
  212.         return;
  213.     for (i = 0; i < maxROWS; i++) {
  214.         (void) memmove(buf_save[appres.save_lines+i],
  215.                     screen_buf + (i*COLS),
  216.                     COLS);
  217.         (void) memmove(ea_save[appres.save_lines+i],
  218.                     (ea_buf + (i*COLS)),
  219.                     COLS*sizeof(struct ea));
  220.     }
  221.     need_saving = False;
  222. }
  223.  
  224. /*
  225.  * Redraw the display so it begins back <sb> lines.
  226.  */
  227. static void
  228. sync_scroll(int sb)
  229. {
  230.     int slop;
  231.     int i;
  232.     int scroll_first;
  233.     float tt0;
  234.  
  235.     unselect(0, ROWS*COLS);
  236.  
  237.     /*
  238.      * If in 3270 mode, round to a multiple of the screen size and
  239.      * set the scroll bar.
  240.      */
  241.     if (ever_3270) {
  242.         if ((slop = (sb % maxROWS))) {
  243.             if (slop <= maxROWS/2)
  244.                 sb -= slop;
  245.             else
  246.                 sb += maxROWS - slop;
  247.         }
  248.         if (sb)
  249.             kybd_scroll_lock(True);
  250.         else
  251.             kybd_scroll_lock(False);
  252.     }
  253.  
  254.     /* Update the status line. */
  255.     if (ever_3270)
  256.         status_scrolled(sb / maxROWS);
  257.     else
  258.         status_scrolled(0);
  259.  
  260.     /* Swap screen sizes. */
  261.     if (sb && !scrolled_back && ((COLS < maxCOLS) || (ROWS < maxROWS))) {
  262.         COLS = maxCOLS;
  263.         ROWS = maxROWS;
  264.         vscreen_swapped = True;
  265.     } else if (!sb && scrolled_back && vscreen_swapped) {
  266.         ctlr_shrink();
  267.         COLS = 80;
  268.         ROWS = 24;
  269.         vscreen_swapped = False;
  270.     }
  271.  
  272.     scroll_first = (scroll_next+appres.save_lines-sb) % appres.save_lines;
  273.  
  274.     /* Update the screen. */
  275.     for (i = 0; i < maxROWS; i++)
  276.         if (i < sb) {
  277.             (void) memmove(screen_buf + (i*COLS),
  278.                     buf_save[(scroll_first+i) % appres.save_lines],
  279.                     COLS);
  280.             (void) memmove((ea_buf + (i*COLS)),
  281.                     ea_save[(scroll_first+i) % appres.save_lines],
  282.                     COLS*sizeof(struct ea));
  283.         } else {
  284.             (void) memmove(screen_buf + (i*COLS),
  285.                     buf_save[appres.save_lines+i-sb],
  286.                     COLS);
  287.             (void) memmove((ea_buf + (i*COLS)),
  288.                     ea_save[appres.save_lines+i-sb],
  289.                     COLS*sizeof(struct ea));
  290.         }
  291.  
  292.     /* Disable the cursor if we're scrolled back, enable it if not. */
  293.     enable_cursor(sb == 0);
  294.  
  295.     scrolled_back = sb;
  296.     ctlr_changed(0, ROWS*COLS);
  297.     blink_start();
  298.  
  299.     tt0 = ((float)n_saved / (float)(appres.save_lines + maxROWS));
  300.     thumb_shown = 1.0 - tt0;
  301.     thumb_top = ((float)(n_saved-sb) / (float)(appres.save_lines + maxROWS));
  302.     screen_set_thumb(thumb_top, thumb_shown);
  303. }
  304.  
  305. /*
  306.  * Callback for "scroll" action (incrementing the thumb in one direction).
  307.  */
  308. void
  309. scroll_proc(int n, int total)
  310. {
  311.     float pct;
  312.     int nss;
  313.     int nsr;
  314.  
  315.     if (!n_saved)
  316.         return;
  317.     if (n < 0)
  318.         pct = (float)(-n) / (float)total;
  319.     else
  320.         pct = (float)n / (float)total;
  321.     /*printf("scroll_proc(%d, %d) %f\n", n, total, pct);*/
  322.     nss = pct * thumb_shown * n_saved;
  323.     if (!nss)
  324.         nss = 1;
  325.     save_image();
  326.     if (n > 0) {    /* scroll forward */
  327.         if (nss > scrolled_back)
  328.             sync_scroll(0);
  329.         else {
  330.             nsr = scrolled_back - nss;
  331.             if (ever_3270 && (nsr % maxROWS))
  332.                 nsr -= nsr % maxROWS;
  333.             sync_scroll(nsr);
  334.         }
  335.     } else {    /* scroll back */
  336.         if (scrolled_back + nss > n_saved)
  337.             sync_scroll(n_saved);
  338.         else {
  339.             nsr = scrolled_back + nss;
  340.             if (ever_3270 && (nsr % maxROWS))
  341.                 nsr += maxROWS - (nsr % maxROWS);
  342.             sync_scroll(nsr);
  343.         }
  344.     }
  345.  
  346.     screen_set_thumb((float)(n_saved - scrolled_back) / (float)(appres.save_lines + maxROWS),
  347.         thumb_shown);
  348. }
  349.  
  350. /*
  351.  * Callback for "jump" action (moving the thumb to a particular spot).
  352.  */
  353. void
  354. jump_proc(float top)
  355. {
  356.     /*printf("jump_proc(%f)\n", top);*/
  357.     if (!n_saved) {
  358.         screen_set_thumb(thumb_top, thumb_shown);
  359.         return;
  360.     }
  361.     if (top > thumb_top_base) {    /* too far down */
  362.         screen_set_thumb(thumb_top_base, thumb_shown);
  363.         sync_scroll(0);
  364.     } else {
  365.         save_image();
  366.         sync_scroll((int)((1.0 - top) * n_saved));
  367.     }
  368. }
  369.  
  370. /*
  371.  * Resynchronize the thumb (called when the scrollbar is turned on).
  372.  */
  373. void
  374. rethumb(void)
  375. {
  376.     screen_set_thumb(thumb_top, thumb_shown);
  377. }
  378.